package mythread;

/**
 * @Auther: cty
 * @Date: 2020/1/9 12:38  存在疑问？？？
 * @Description:  指令重排：代码执行顺序与预期不一致
 *
 * 1、为什么会进行指令重排？
 * 内存操作速度远远慢于CPU运行速度，为了【提高性能】在【虚拟机层面和硬件层面】，
 * 会将【单线程下不存在数据依赖】的操作进行指令重排。
 *
 * 2、什么是操作之间的数据依赖？
 * 两个操作访问同一个变量，且其中一个为写操作。（数据依赖的两个操作）
 * 写后读
 * 写后写
 * 读后写
 *
 * 3、代码运行过程？
 *（1）从内存抓取指令
 *（2）从寄存器拷贝数据到工作台
 *（3）对数据进行操作
 *（4）将数据写回寄存器
 *
 * 参考博客
 * （1）jvm住内存与工作内存，内存模型反映的java多线程问题
 * https://blog.csdn.net/sc313121000/article/details/40266531

 * @version: 1.0
 */
public class Jc_Other_HappyBefore {
    //变量1
    private static int a = 0;
    //变量2
    private static boolean flag = false;
    public static void main(String[] args) throws InterruptedException {
        for(int i=0; i<100; i++){
            a = 0;
            flag = false;
            //线程1
            Thread t1 = new Thread(()->{
                a = 1;
                flag = true;
            });
            //线程2
            Thread t2 = new Thread(()->{
                if(flag){
                    a *= 1;
                }
                //可能出现指令重排？？？
                if(a==0){
                    System.out.println("happy before->"+a);
                }
            });

            t1.start();
            t2.start();

            t1.join();  //让线程1先执行
            t2.join();
        }
    }
}
/*结果
happy before->0
happy before->0
happy before->0
happy before->0
happy before->0
happy before->1
happy before->0
*/

/*
循环100次，
（1）93次输出结果为空，按照预期执行
（2）6次输出结果为happy before->0，是因为指令重排，线程2先于线程1执行
（3）1次输出结果为happy before->1，是因为虽然线程1先执行，由于数据从工作区写回寄存器需要时间，发生指令重排，
线程2执行，此时寄存器中a=0、flag=false打印结果，但打印时
*/